package org.one.stone.soup.grfxML.plugin.builder;

import org.one.stone.soup.grfxML.DataChildren;
import org.one.stone.soup.grfxML.DataNode;
import org.one.stone.soup.grfxML.DataPoint;
import org.one.stone.soup.grfxML.DataShape;
import org.one.stone.soup.grfxML.DataState;
import org.one.stone.soup.grfxML.GrfxMLEngine;
import org.one.stone.soup.grfxML.GrfxMLProcessor;
import org.one.stone.soup.grfxML.TagModifier;
import org.one.stone.soup.grfxML.plugin.SimplePlugin;
import org.one.stone.soup.grfxML.plugin.grfxMLCaster;
import org.one.stone.soup.mjdb.data.field.DataLinker;
import org.one.stone.soup.mjdb.data.field.Field;
import org.one.stone.soup.mjdb.data.field.LockException;

public class Edit extends SimplePlugin {

	private static int ID = 0;

	private static final int ARG_DELETE = 0;
	private static final int ARG_CUT = 1;
	private static final int ARG_COPY = 2;
	private static final int ARG_PASTE = 3;

	private static DataNode clipboard = null;

	private DataState delete = new DataState();
	private DataState cut = new DataState();
	private DataState copy = new DataState();
	private DataState paste = new DataState();

	private boolean processing = false;
/**
 * NodeBuilder constructor comment.
 */
public Edit(GrfxMLEngine engine){
	super(engine);
}
/**
 * initialize method comment.
 */
public void initialize() {}
/**
 * process method comment.
 */
public void process()
{
	if(processing==true)
		return;

	if( (delete.getValue()==true || cut.getValue()==true) && isHolding())//CUT and DEL
	{
		processing=true;
		getEngine().getAPI().setAutoCommit(false);

		if(cut.getValue()==true)
		{
			clipboard = getHeld();
		}
		removeNode( getHeld() );

		getEngine().getAPI().commit();
		processing=false;
	}
	else if(copy.getValue()==true && isHolding())//COPY
	{
		processing=true;
		getEngine().getAPI().setAutoCommit(false);

		clipboard = getHeld();

		getEngine().getAPI().commit();
		processing=false;
	}
	else if(paste.getValue()==true && clipboard!=null)//PASTE
	{
		processing=true;
		getEngine().getAPI().setAutoCommit(false);

		pasteNode();

		getEngine().getAPI().commit();
		processing=false;
	}
}
/**
 * register method comment.
 */
public void register(DataLinker store)
{
	delete	=	grfxMLCaster.cast(delete,getArg(delete,ARG_DELETE,store));
	cut	=	grfxMLCaster.cast(cut,getArg(cut,ARG_CUT,store));
	copy	=	grfxMLCaster.cast(copy,getArg(copy,ARG_COPY,store));
	paste	=	grfxMLCaster.cast(paste,getArg(paste,ARG_PASTE,store));
}
/**
 * replace method comment.
 */
public void replace(Field oldObj, Field newObj)
{
	cut	=	grfxMLCaster.replace(cut,oldObj,newObj);
	copy	=	grfxMLCaster.replace(copy,oldObj,newObj);
	paste	=	grfxMLCaster.replace(paste,oldObj,newObj);
	delete	=	grfxMLCaster.replace(delete,oldObj,newObj);
}

private boolean isHolding()
{
	if( getEngine().getAPI().getMouse().getHeld() == null)
	{
		return false;
	}
	else
	{
		return true;
	}
}

private DataNode getHeld()
{
	Object held = getEngine().getAPI().getMouse().getHeld();

	if(held==null)
	{
		return null;
	}
	else
	{
		return (DataNode)held;
	}
}

private void removeNode(DataNode node)
{
	getEngine().getAPI().remove( node,node.getParent().getChildren() );
}

private void pasteNode()
{
	DataNode target = findTarget( getEngine().getAPI().getBase().getROOT().getChildren(),getEngine().getAPI().getMouse().getPosition() );
	if(target==null)
	{
		target = getEngine().getAPI().getBase().getROOT();
	}

	try{
		DataNode newNode = clipboard.getClone( getNextId() );
		DataPoint position = getEngine().getAPI().getMouse().getPosition();
		newNode.getTranslation().getPosition().setValueX( position.getValueX()-target.getTranslation().getPosition().getValueX(),this );
		newNode.getTranslation().getPosition().setValueY( position.getValueY()-target.getTranslation().getPosition().getValueY(),this );

		target.getChildren().add( newNode ,this);
	}
	catch(LockException le){}
}

private DataNode findTarget( DataChildren children,DataPoint pointView )
{
	for(int loop=0;loop<children.size();loop++)
	{
		DataNode node = children.get(loop);

		DataNode found = findTarget( node.getChildren(),pointView );

		if(found!=null)
		{
			return found;
		}

		DataPoint point = new DataPoint();
		try{
			GrfxMLProcessor.reverseTranslate(pointView,TagModifier.POINT_TYPE_POINT,node.getTranslation(),point);
		}
		catch(Exception e)
		{
			continue;
		}

		DataShape shape = node.getShape();
		for(int loopS=0;loopS<shape.size();loopS++)
		{
			if( shape.get(loopS).getGeometry(getEngine()).contains(point,pointView) )
			{
				return node;
			}
		}
	}

	return null;
}

private String getNextId()
{
	ID++;

	return "pasted."+ID;
}

/**
 * stop method comment.
 */
public void stop() {}
}
